package com.zp.base.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.base.api.entity.PriceList;
import com.zp.base.api.entity.PriceListLog;
import com.zp.base.entity.ClinicVsPrice;
import com.zp.base.entity.bo.PriceListBo;
import com.zp.base.entity.bo.PriceListLogBo;
import com.zp.base.entity.vo.ClinicVsPriceVo;
import com.zp.base.entity.vo.PriceListVo;
import com.zp.base.mapper.ClinicVsPriceMapper;
import com.zp.base.mapper.PriceListLogMapper;
import com.zp.base.mapper.PriceListMapper;
import com.zp.base.service.IPriceListLogService;
import com.zp.base.service.IPriceListService;
import com.zp.common.core.constant.PriceConstants;
import com.zp.common.core.utils.DateUtils;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.satoken.utils.LoginHelper;
import com.zp.system.api.entity.LoginUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 价表Service业务层处理
 *
 * @author zhang peng
 * @date 2023-01-05
 */
@RequiredArgsConstructor
@Service
public class PriceListServiceImpl implements IPriceListService {

    private final PriceListMapper baseMapper;

    private final PriceListLogMapper priceListLogMapper;
    private final IPriceListLogService priceListLogService;

    private final ClinicVsPriceMapper clinicVsPriceMapper;

    /**
     * 查询价表
     */
    @Override
    public PriceListVo queryById (String priceId) {
        return baseMapper.selectVoById(priceId);
    }

    /**
     * 查询价表列表(分页)
     */
    @Override
    public TableDataInfo<PriceListVo> queryPageList (PriceListBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<PriceList> lqw = buildQueryWrapper(bo);
        Page<PriceListVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询价表列表(不分页)
     */
    @Override
    public List<PriceListVo> queryList (PriceListBo bo) {
        LambdaQueryWrapper<PriceList> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<PriceList> buildQueryWrapper (PriceListBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<PriceList> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getItemClass()), PriceList::getItemClass, bo.getItemClass());
        lqw.eq(StringUtils.isNotBlank(bo.getItemCode()), PriceList::getItemCode, bo.getItemCode());
        lqw.like(StringUtils.isNotBlank(bo.getItemName()), PriceList::getItemName, bo.getItemName());
        lqw.eq(StringUtils.isNotBlank(bo.getItemSpec()), PriceList::getItemSpec, bo.getItemSpec());
        lqw.eq(StringUtils.isNotBlank(bo.getMedicalInsuranceType()), PriceList::getMedicalInsuranceType, bo.getMedicalInsuranceType());
        lqw.eq(StringUtils.isNotBlank(bo.getUnits()), PriceList::getUnits, bo.getUnits());
        lqw.eq(bo.getNetworkPrice() != null, PriceList::getNetworkPrice, bo.getNetworkPrice());
        lqw.eq(bo.getTradePrice() != null, PriceList::getTradePrice, bo.getTradePrice());
        lqw.eq(bo.getPrice() != null, PriceList::getPrice, bo.getPrice());
        lqw.eq(bo.getPreferPrice() != null, PriceList::getPreferPrice, bo.getPreferPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getClassOnRcpt()), PriceList::getClassOnRcpt, bo.getClassOnRcpt());
        lqw.eq(StringUtils.isNotBlank(bo.getClassOnInp()), PriceList::getClassOnInp, bo.getClassOnInp());
        lqw.eq(StringUtils.isNotBlank(bo.getClassOnReckoning()), PriceList::getClassOnReckoning, bo.getClassOnReckoning());
        lqw.eq(StringUtils.isNotBlank(bo.getSubjCode()), PriceList::getSubjCode, bo.getSubjCode());
        lqw.eq(StringUtils.isNotBlank(bo.getClassOnMr()), PriceList::getClassOnMr, bo.getClassOnMr());
        lqw.eq(bo.getStartDate() != null, PriceList::getStartDate, bo.getStartDate());
        lqw.eq(bo.getStopDate() != null, PriceList::getStopDate, bo.getStopDate());
        lqw.eq(StringUtils.isNotBlank(bo.getInputCode()), PriceList::getInputCode, bo.getInputCode());
        lqw.eq(PriceList::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getItemCodeYbCompare()), PriceList::getItemCodeYbCompare, bo.getItemCodeYbCompare());
        lqw.eq(StringUtils.isNotBlank(bo.getZfOrYb()), PriceList::getZfOrYb, bo.getZfOrYb());
        lqw.orderByAsc(PriceList::getItemClass);
        return lqw;
    }

    /**
     * 新增价表
     */
    @Override
    public Boolean insertByBo (PriceListBo bo) {
        PriceList add = BeanUtil.toBean(bo, PriceList.class);
        validEntityBeforeSave(add);
        add.setDelFlag("0");
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setPriceId(add.getPriceId());
            bo.setOperationType(PriceConstants.OPERATION_TYPE_INSERT);
            initPriceListLog(bo);
        }
        return flag;
    }

    /**
     * 修改价表
     */
    @Override
    public Boolean updateByBo (PriceListBo bo) {
        PriceList update = BeanUtil.toBean(bo, PriceList.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave (PriceList entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除价表
     */
    @Override
    public Boolean deleteWithValidByIds (Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 停价
     *
     * @param priceId
     * @return
     */
    @Override
    public Boolean stopPrice (String priceId) {
        PriceList price = baseMapper.selectById(priceId);
        price.setStopDate(DateUtils.getNowDate());
        baseMapper.updateById(price);
        PriceListBo bo = BeanUtil.toBean(price, PriceListBo.class);
        bo.setPriceId(priceId);
        bo.setOperationType(PriceConstants.OPERATION_TYPE_STOPPRICE);
        return initPriceListLog(bo);
    }

    /**
     * 调价
     *
     * @param bo
     * @return
     */
    @Override
    public Boolean priceAdjustment (PriceListBo bo) {
        PriceList price = baseMapper.selectById(bo.getPriceId());
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (ObjectUtil.isNotNull(price)) {
            price.setPrice(bo.getPrice());
            price.setStartDate(bo.getStartDate());
            price.setUpdateBy(loginUser.getUsername());
            price.setUpdateTime(DateUtils.getNowDate());
            baseMapper.updateById(price);
            bo = BeanUtil.toBean(price, PriceListBo.class);
            bo.setOperationType(PriceConstants.OPERATION_TYPE_PRICEADJUSTMENT);
            return initPriceListLog(bo);
        }
        return false;
    }

    /**
     * 启用
     *
     * @param bo
     * @return
     */
    @Override
    public Boolean priceEnable (PriceListBo bo) {
        PriceList price = baseMapper.selectById(bo.getPriceId());
        price.setStopDate(null);
        price.setStartDate(DateUtils.getNowDate());
        baseMapper.updatePriceEnable(price);
        bo.setStartDate(price.getStartDate());
        bo.setStopDate(null);
        bo.setOperationType(PriceConstants.OPERATION_TYPE_ENABLE);
        return initPriceListLog(bo);

    }

    ;

    /**
     * 停价、调价 业务处理
     *
     * @param bo
     */
    public Boolean initPriceListLog (PriceListBo bo) {
        PriceListLogBo priceListLogBo = BeanUtil.toBean(bo, PriceListLogBo.class);
        LoginUser loginUser = LoginHelper.getLoginUser();
        priceListLogBo.setCreateBy(loginUser.getUsername());
        priceListLogBo.setCreateTime(DateUtils.getNowDate());
        switch (bo.getOperationType()) {
            case PriceConstants.OPERATION_TYPE_INSERT:
                // 新增
                priceListLogBo.setIsNer(PriceConstants.IS_NER_YES);
                break;
            case PriceConstants.OPERATION_TYPE_EDIT:
                // 修改
                break;
            case PriceConstants.OPERATION_TYPE_PRICEADJUSTMENT:
                // 调价
                // 获取已存在的记录
                List<PriceListLog> priceListLogList = getPriceListLog(bo);
                if (CollectionUtil.isNotEmpty(priceListLogList)) {
                    // 循环修改 是否最新价格 字段为 否
                    priceListLogList.forEach(item -> {
                        if (item.getStopDate() == null) {
                            item.setIsNer(PriceConstants.IS_NER_NO);
                            item.setStopDate(bo.getStartDate());
                            item.setUpdateBy(loginUser.getUsername());
                            item.setUpdateTime(DateUtils.getNowDate());
                            priceListLogMapper.updateById(item);
                        }
                    });
                    priceListLogBo.setIsNer(PriceConstants.IS_NER_YES);
                }
                break;
            case PriceConstants.OPERATION_TYPE_STOPPRICE:
                // 停价
                // 获取已存在的记录
                List<PriceListLog> priceListLogListStop = getPriceListLog(bo);
                if (CollectionUtil.isNotEmpty(priceListLogListStop)) {
                    priceListLogListStop.forEach(item -> {
                        if (item.getStopDate() == null) {
                            item.setStopDate(DateUtils.getNowDate());
                            item.setIsNer(PriceConstants.IS_NER_NO);
                            item.setUpdateBy(loginUser.getUsername());
                            item.setUpdateTime(DateUtils.getNowDate());
                            priceListLogMapper.updateById(item);
                        }
                    });
                }
                priceListLogBo.setStopDate(DateUtils.getNowDate());
                priceListLogBo.setUpdateBy(loginUser.getUsername());
                priceListLogBo.setIsNer(PriceConstants.IS_NER_YES);
                break;
            case PriceConstants.OPERATION_TYPE_ENABLE:
                // 启用
                priceListLogBo.setIsNer(PriceConstants.IS_NER_YES);
                break;
            case PriceConstants.OPERATION_TYPE_OTHER:
                // 其他
                break;
            default:
                break;
        }
        return priceListLogService.insertByBo(priceListLogBo);
    }

    /**
     * 获取已存在的记录
     *
     * @param bo
     * @return
     */
    public List<PriceListLog> getPriceListLog (PriceListBo bo) {

        List<PriceListLog> priceListLogList = priceListLogMapper.selectList(Wrappers.<PriceListLog>lambdaQuery()
                .eq(PriceListLog::getPriceId, bo.getPriceId())
                .eq(PriceListLog::getOrgId, bo.getOrgId())
        );
        return priceListLogList;
    }

    /**
     * 当前价表自动补全
     *
     * @param bo
     * @return
     */
    @Override
    public List<PriceListVo> getCurrentPriceList (PriceListBo bo) {
        List<PriceListVo> result = baseMapper.getCurrentPriceList(bo);
        if (bo.getIsFiltrationContrastExist()) {
            List<ClinicVsPriceVo> clinicVsPriceBoList = clinicVsPriceMapper.selectVoList(Wrappers.<ClinicVsPrice>lambdaQuery()
                    .eq(ClinicVsPrice::getClinicItemId, bo.getClinicItemId()));
            if (CollectionUtil.isNotEmpty(clinicVsPriceBoList)) {
                result = result.stream().filter(item -> clinicVsPriceBoList.stream().noneMatch(d -> item.getPriceId().equals(d.getPriceId()))).collect(Collectors.toList());
            }
        }
        return result;
    }

    /**
     * 获取诊疗项目已对照的价表
     *
     * @param bo
     * @return
     */
    @Override
    public List<PriceListVo> selectContrastExist (PriceListBo bo) {
        List<PriceListVo> list = baseMapper.selectContrastExist(bo);
        if (CollectionUtil.isNotEmpty(list)) {
            list.forEach(item -> {
                item.setSubTotal(item.getPrice().doubleValue() * item.getClinicVsPriceVo().getAmount());
            });
        }
        return list;
    }
}
